package com.ggkt.common.utils.dao;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 分页模型
 * </p>
 * 
 * @author ggkt
 */
@SuppressWarnings("serial")
public class Page<T> implements Serializable {

	/** 分页数据 */
	private List<T> datas;

	/** 分页总数 */
	private int total;

	/** 分页大小 */
	private int pageSize = 10;

	/**
	 * 分页数据开始位置（偏移量），从0开始
	 */
	private int offset = 0;

	private int end = -1;

	/** 第一页数 */
	private int firstPage = 1;

	/** 总页数 */
	private int totalPage;

	/** 当前页数 */
	private int currentPage;

	/**
	 * 页码展示列表 风格: 1... 2 3 4 5 6 7 8 9 10 11 ...24
	 */
	private List<PageNo> pageNos;

	/** 上一页码 */
	private int prevPage;

	/** 下一页码 */
	private int nextPage;

	public Page() {
		this(0, 0, 0);
	}

	public Page(int total, int offset) {
		this(total, 50, offset);
	}

	public static <X> Page<X> newByPageNo(int total, int pageSize, int currentPage) {

		return new Page<>(total, pageSize, pageSize * (currentPage - 1));
	}

	public static <T> Page<T> newByPageNo(int total, int pageSize, int currentPage, List<T> datas) {
		Page<T> page = Page.newByPageNo(total, pageSize, currentPage);
		page.setDatas(datas);
		return page;
	}

	public static <X> Page<X> newByOffset(int total, int pageSize, int offset) {

		return new Page<>(total, pageSize, offset);
	}

	/**
	 * 初始化分页模型
	 * 
	 * @param total    总数
	 * @param pageSize 每页数据大小
	 * @param offset   分页，数据开始位置，从0开始
	 */
	public Page(int total, int pageSize, int offset) {

		this.total = total;
		this.pageSize = pageSize;
		this.offset = offset;

		if (this.total <= 0) {
			return;
		}

		if (this.pageSize <= 0) {
			this.pageSize = 10;
		} else if (this.pageSize > 100) {
			this.pageSize = 100;
		}

		this.totalPage = this.total % this.pageSize == 0 ? this.total / this.pageSize : this.total / this.pageSize + 1;

		int maxOffset = 0;
		if (this.offset < 0) {
			this.offset = 0;
		} else if (this.offset > (maxOffset = (this.totalPage - 1) * this.pageSize)) {
			this.offset = maxOffset;
		}

		this.end = this.offset + this.pageSize - 1;

		int ts = this.offset + 1;

		this.currentPage = ts % pageSize == 0 ? ts / pageSize : ts / pageSize + 1;
	}

	/**
	 * 前5页，后5页数据，定义为热数据
	 */
	public boolean isHotData() {

		return this.currentPage <= 5 || this.currentPage > this.totalPage - 5;
	}

	/** 是否还有上一页 */
	public boolean isHasPrevPage() {

		return this.currentPage > this.firstPage;
	}

	/** 是否还有下一页 */
	public boolean isHasNextPage() {

		return this.currentPage < this.totalPage;
	}

	/** 上一页数 */
	public int getPrevPage() {

		if (this.isHasPrevPage()) {
			this.prevPage = this.currentPage - 1;
		} else {
			this.prevPage = this.currentPage;
		}

		return prevPage;
	}

	/** 下一页数 */
	public int getNextPage() {

		if (this.isHasNextPage()) {
			this.nextPage = this.currentPage + 1;
		} else {
			this.nextPage = this.currentPage;
		}

		return nextPage;
	}

	/** 上一页--开始的数据偏移量 */
	public int getPrevPageOffset() {

		return (this.getPrevPage() - 1) * this.pageSize;
	}

	/** 下一页数--开始的数据偏移量 */
	public int getNextPageOffset() {

		return (this.getNextPage() - 1) * this.pageSize;
	}

	/** 下一页数--开始的数据偏移量 */
	public int getLastPageOffset() {

		return (this.totalPage - 1) * this.pageSize;
	}

	/** 第一页数 */
	public int getFirstPage() {

		return firstPage;
	}

	/** 当前页 数据结束位置（开始数据是从0开始） */
	public int getEnd() {

		if (this.end == -1) {
			this.end = this.currentPage * this.pageSize - 1;
			if (this.end > this.total - 1) {
				this.end = this.total - 1;
			}
		}

		return this.end;
	}

	public int getStartNo() {

		return (this.currentPage - 1) * this.pageSize + 1;
	}

	public int getEndNo() {

		int temp = this.currentPage * this.pageSize;

		return temp <= this.total ? temp : this.total;
	}

	/**
	 * 获取展示的页码 风格1
	 * 
	 * ps: 1... 2 3 4 5 6 7 8 9 10 11 ...24
	 */
	List<PageNo> generatePageNos() {

		List<PageNo> pageNos = new ArrayList<PageNo>();
		if (this.totalPage <= 11) {
			for (int i = 1; i <= this.totalPage; i++) {
				pageNos.add(new PageNo(i, this.pageSize * (i - 1)));
			}
		} else {
			int start = 0, end = 0;
			String startstr = null, endstr = null;
			if (this.currentPage <= 6) {
				start = 1;
				end = 10;
				endstr = "...";
			} else if (this.totalPage - this.currentPage <= 4) {
				startstr = "...";
				start = this.totalPage - 9;
				end = this.totalPage;
			} else {
				startstr = "...";
				start = this.currentPage - 5;
				end = this.currentPage + 4;
				endstr = "...";
			}

			if (startstr != null) {
				pageNos.add(new PageNo(1, 0, 1 + startstr));
			}
			for (int i = start; i <= end; i++) {
				pageNos.add(new PageNo(i, this.pageSize * (i - 1)));
			}
			if (endstr != null) {
				pageNos.add(new PageNo(this.totalPage, this.pageSize * (this.totalPage - 1), endstr + this.totalPage));
			}
		}

		return pageNos;
	}

	/**
	 * 获取展示的页码 风格1
	 * 
	 * ps: 1 2 3 4 5 ps: 4 5 6 7 8 ps: 6 7 8 9 10
	 */
	List<PageNo> createSimplePageNos() {

		List<PageNo> pageNos = new ArrayList<PageNo>();
		if (this.totalPage <= 5) {
			for (int i = 1; i <= this.totalPage; i++) {
				pageNos.add(new PageNo(i, this.pageSize * (i - 1)));
			}
		} else {
			int start = 0, end = 0;
			if (this.currentPage <= 3) {
				start = 1;
				end = 5;
			} else if (this.totalPage - this.currentPage <= 2) {
				start = this.totalPage - 4;
				end = this.totalPage;
			} else {
				start = this.currentPage - 2;
				end = this.currentPage + 2;
			}

			for (int i = start; i <= end; i++) {
				pageNos.add(new PageNo(i, this.pageSize * (i - 1)));
			}
		}

		return pageNos;
	}

	public List<T> getDatas() {
		return datas;
	}

	public void setDatas(List<T> datas) {
		this.datas = datas;
	}

	public int getTotal() {
		return total;
	}

	public int getPageSize() {
		return pageSize;
	}

	public int getTotalPage() {
		return totalPage;
	}

	public int getCurrentPage() {
		return currentPage;
	}

	/**
	 * 分页数据列表其实位置，偏移量，从0开始
	 */
	public int getOffset() {
		return offset;
	}

	public void setOffset(int offset) {
		this.offset = offset;
	}

	public List<PageNo> getPageNos() {

		if (this.pageNos == null) {
			this.pageNos = this.createSimplePageNos();
		}

		return pageNos;
	}
}